package com.smy.bc.fabric.api.controller;

import com.smy.bc.fabric.core.FabricTemplate;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.hyperledger.fabric.sdk.ProposalResponse;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric.sdk.exception.ProposalException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Collection;

/**
 * <p>Title: FabricApiController</p>
 * <p>Description: </p>
 *
 * @author zhaofeng
 * @version 1.0
 * @date 18-9-12
 */
@Api(value = "/")
@RestController
@RequestMapping("/")
@Slf4j
public class FabricApiController {

    @Resource
    private FabricTemplate fabricTemplate;


    @ApiOperation(value = "启动事件监听")
    @RequestMapping(value = "chaincodeEvent",method = RequestMethod.GET)
    public String chaincodeEvent(){
        String s = fabricTemplate.registerChaincodeEventListener();
        return "启动区块链事件监听"+s;
    }

    @ApiOperation(value = "解绑事件监听")
    @ApiImplicitParam(name = "handle" ,value = "区块事件监听handle",paramType = "query",required = true)
    @RequestMapping(value = "unchaincodeEvent",method = RequestMethod.POST)
    public String unchaincodeEvent(String handle){
        boolean s = fabricTemplate.unregisterChaincodeEventListener(handle);
        return handle+" 事件监听解绑:"+s;
    }


    @ApiOperation(value = "启动区块监听")
    @RequestMapping(value = "blockEvent",method = RequestMethod.GET)
    public String blockEvent(){
        String s = fabricTemplate.registerBlockListener();
        return "启动区块事件监听"+s;
    }

    @ApiOperation(value = "解绑事件监听")
    @ApiImplicitParam(name = "handle" ,value = "区块监听handle",paramType = "query",required = true)
    @RequestMapping(value = "unblockEvent",method = RequestMethod.POST)
    public String unblockEvent(String handle){
        boolean s = fabricTemplate.unregisterBlockListener(handle);
        return handle+" 事件监听解绑:"+s;
    }


    @ApiOperation(value = "查询智能合约", notes = "使用方式 list|query args[]|history args[]")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "funcName",value = "查询接口",allowableValues = "list,query,history", paramType = "query", dataType = "string", required = true),
            @ApiImplicitParam(name = "funcName", value = "查询参数",example = "key1", paramType = "query", dataType = "string", allowMultiple = true)
    })
    @RequestMapping(value = "query", method = RequestMethod.POST)
    public String query(String funcName, String... args) {

        if (args == null) {
            args = new String[] {};
        }

        try {
            Collection<ProposalResponse> list = fabricTemplate.queryBlockChain(funcName, args);

            StringBuilder sb = new StringBuilder();
            for (ProposalResponse response : list) {
                if (response.isInvalid()){
                    sb.append("Payload:").append(new String(response.getMessage())).append("\n");
                }else {
                    sb.append("Payload:").append(new String(response.getChaincodeActionResponsePayload())).append("\n");
                }
            }

            return sb.toString();
        } catch (ProposalException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        }
        return "query 异常!";
    }

    @RequestMapping()
    public String index() {
        return "fabric-api启动成功!";
    }

    @ApiOperation(value = "调用智能合约", notes = "使用方式 create args[],update args[],init args[],invoke args[]")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "funcName", value = "智能合约方法",allowableValues = "create,update,init,invoke", paramType = "query", dataType = "string", required = true),
            @ApiImplicitParam(name = "args",value = "调用参数",example = "[\"key1\",\"value\"]", paramType = "query", dataType = "string", allowMultiple = true)
    })
    @RequestMapping(value = "invoke", method = RequestMethod.POST)
    public String invoke(String funcName, String... args) {
        try {
            fabricTemplate.invokeBlockChain(funcName, args);
        } catch (ProposalException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        }
        return funcName + " 调用完成";
    }

}
